﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Options;
using Microsoft.VisualBasic.CompilerServices;
using MySqlConnector;
using NetMicro.Core.Extensions;
using NetMicro.EventBus.Extensions;
using NetMicro.EventBus.Messages;
using NetMicro.EventBus.Persistences;

namespace NetMicro.EventBus.MySql
{
    public class DeadLetterMessageStorage : IDeadLetterMessageStorage
    {
        public DeadLetterMessageStorage(IOptionsMonitor<EventBusMySqlOptions> options)
        {
            Options = options;
        }


        private IOptionsMonitor<EventBusMySqlOptions> Options { get; }
        public async Task<bool> SaveAsync(MessageStorageTransfer message, IDbTransaction transaction = null, CancellationToken cancellationToken = default)
        {
            var sql = $@"
INSERT INTO `{Options.CurrentValue.DeadLetterTableName}`
(`Id`,`EventBody`, `CreateTime`, `ExpireTime`, `EventName`, `Version`, `EventHandlerName`, `MsgId`,`Exception`,`RetryCount`)
VALUES(@Id,@EventBody, @CreateTime, @ExpireTime, @EventName, @Version, @EventHandlerName, @MsgId,@Exception,@RetryCount);
";
            var parameters = new[]
            {
                new MySqlParameter("@Id", MySqlDbType.Int64) {Value = message.Id},
                new MySqlParameter("@EventBody", MySqlDbType.VarChar) {Value = message.EventBody},
                new MySqlParameter("@CreateTime", MySqlDbType.Int64) {Value = message.CreateTime},
                new MySqlParameter("@ExpireTime", MySqlDbType.Int64) {Value = Options.CurrentValue.DeadLetterMessageExpireTime.GetTimestampSeconds()},
                new MySqlParameter("@EventName", MySqlDbType.Int64) {Value = message.EventName},
                new MySqlParameter("@Version", MySqlDbType.VarChar) {Value = message.Version},
                new MySqlParameter("@EventHandlerName", MySqlDbType.Bit) {Value = message.EventHandlerName},
                new MySqlParameter("@MsgId", MySqlDbType.Int64) {Value = message.MsgId},
                new MySqlParameter("@Exception", MySqlDbType.Int64) {Value = message.Exception},
                new MySqlParameter("@RetryCount", MySqlDbType.Int64) {Value = message.RetryCount},
            };

            if (transaction == null)
            {
                await using var connection = new MySqlConnection(Options.CurrentValue.ConnectionString);
                return connection.ExecuteNonQuery(sql, sqlParams: parameters) > 0;
            }
            else
            {
                var conn = transaction?.Connection;
                return conn.ExecuteNonQuery(sql, transaction, parameters) > 0;
            }
        }

        /// <summary>
        /// 删除到期消息
        /// </summary>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<bool> DeleteExpiresAsync(CancellationToken cancellationToken = default)
        {
            var now = TimeSpan.Zero.GetTimestampSeconds();
            var sql = $@"DELETE FROM `{Options.CurrentValue.DeadLetterTableName}` WHERE `ExpireTime` > 0 AND `ExpireTime` < {now};";
            await using var connection = new MySqlConnection(Options.CurrentValue.ConnectionString);
            return connection.ExecuteNonQuery(sql) > 0;
        }
    }
}
